#include "ResourceSystem.h"
#include <iostream>
#include "Debug.h"

std::map<uint16, Image*>		 ResourceSystem::images;
std::map<std::string, uint16> ResourceSystem::filenames;
uint32 ResourceSystem::m_count = 0;

ResourceSystem::ResourceSystem()
{
	
}


//TODO: Completly rewrite this using a vector?
sf::Image* ResourceSystem::GetImage( const std::string& filename, const sf::Color& alpha /*= sf::Color(0,0,0)*/, bool allowRefCount /*= true*/ )
{
	FilenameMap::iterator itr =  filenames.find(filename);
	uint16 filenameId = itr == filenames.end() ? -1 : itr->second;

	ImageMap::iterator i = images.find(filenameId);
	if(i != images.end()) {
		if(allowRefCount) {
			i->second->refCount++;
		}
		return &i->second->image;
	} else {
		Image* img = new Image;
		filenameId = m_count++;

		if(!img->image.LoadFromFile(filename)) {
			sLog.outError("ResourceSystem::GetImage(): Unable to find: %s", filename.c_str());
			delete img;
			return NULL;
		}
		img->image.CreateMaskFromColor(alpha);
		img->refCount = 1;
		images[filenameId] = img;
		filenames[filename] = filenameId;

		sLog.outDebug("Loading image %s", filename.c_str());
		return &img->image;
	}
	//something went wrong?
	return 0;
}

uint16 ResourceSystem::GetId(const std::string& filename)
{
	FilenameMap ::iterator i = filenames.find(filename);
	if(i == filenames.end()) 
		return -1;
	return i->second;
}

void ResourceSystem::FreeImage(const std::string& filename)
{
	FilenameMap::iterator i = filenames.find(filename);
	if(i == filenames.end())
		return;
	else FreeImage(i->second);
}

void ResourceSystem::FreeImage(uint16 filename)
{
	ImageMap::iterator i = images.find(filename);
	if(i == images.end()) {
		sLog.outError("ResourceSystem::FreeImage(): Couldn't free image: %s.. already freed?", GetName(filename).c_str());
		return;
	}
	uint16 refCount = i->second->refCount;
	FreeImage(i);

	if(refCount <= 1) {
		std::string id = GetName(filename);
		FilenameMap::iterator itr = filenames.find(id);
		if(itr != filenames.end()) {
			filenames.erase(itr);
		} else {
			sLog.outError("ResourceSystem::FreeImage(): Image %s isn't found in filenameMap!", id.c_str());
		}
	}
}

//WATCH OUT! this could erase items from the map! and thus null the pointer
bool ResourceSystem::FreeImage(const ImageMap::iterator& i)
{
	if(i != images.end()) {		//this should be redundant now.. still!
		if(i->second->refCount <= 1) {
			#ifdef _DEBUG
			std::cout << "Freeing image: " << GetName(i->first) << std::endl;
			#endif

			delete i->second;
			images.erase(i);
			return true;
		} else {
			i->second->refCount--;
			return false;
		}
	} else {
		std::cerr << "ResourceSystem::ERROR! Couldn't find image "<< std::endl;
		return false;
	}
}


ResourceSystem::~ResourceSystem()
{
	for(ImageMap::iterator i = images.begin(); i!=images.end(); i++) {
		if(FreeImage(i))
			i = images.begin();
	}
}

std::string ResourceSystem::GetName( uint16 id )
{
	for(FilenameMap::iterator i = filenames.begin(); i != filenames.end(); i++) {
		if(i->second == id) return i->first;
	}
	return "Not found!";
}